// Copyright (c) 2023 刻BITTER
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.


#pragma once


#include <Arduino.h>
#include <Wire.h>


#include "oled_basic_init_sequence.hpp"
#include "oled_basic_low_level_common.hpp"
#include "oled_basic_low_level_ssd13xx_common.hpp"


namespace oled_basic {

    struct ArduinoWire1306 : public CommonWriteCmdAndData<ArduinoWire1306>, public Ssd13xxProtocol<ArduinoWire1306> {
        constexpr static size_t init_sequence_length = sizeof(_init_sequence_for_ssd1306_2_wire_i2c);
        constexpr static const uint8_t (&init_sequence)[init_sequence_length] = _init_sequence_for_ssd1306_2_wire_i2c;

        constexpr static bool manual_start_end_for_data_transfer = false;

        // static void start_transmission() {
        //     Wire.setClock(400e3);
        //     Wire.beginTransmission(0x3c);
        // }

        static void write_byte(uint8_t data_byte, write_mode mode) {
            Wire.setClock(400e3);
            Wire.beginTransmission(0x3c);

            if (mode == write_mode::cmd) {
                Wire.write(0x00);
            }
            else {
                Wire.write(0x40);
            }

            if (mode == write_mode::inverse)
                data_byte = ~data_byte;

            Wire.write(data_byte);   // sends one byte
            Wire.endTransmission();  // stop transmitting
        }

        // static void end_transmission() {
        //     Wire.endTransmission(true);  // stop transmitting
        // }
    };


    struct ArduinoWire1306_12864 : public ArduinoWire1306 {
        constexpr static uint8_t column_count = 128;
        constexpr static uint8_t page_count = 8;
    };

}  // namespace oled_basic